package cn.itcast.web.shiro;

import cn.itcast.service.system.ModuleService;
import cn.itcast.service.system.UserService;
import cn.itcast.domain.system.Module;
import cn.itcast.domain.system.User;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
 * @author LT
 * @version 1.0.0
 * @ClassName AuthRealm.java
 * @Description TODO 自定义reamlm
 * @createTime 2020年03月26日 21:36:00
 */
public class AuthRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Autowired
    private ModuleService moduleService;

    // 认证：当subject调用login方法，就是调用doGetAuthenticationInfo方法！
    //并且doGetAuthenticationInfo方法的token就是login方法传递过来的token。
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //1. 先从token取出用户输入邮箱与密码
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String email = usernamePasswordToken.getUsername();
        //2. 根据邮箱去查找用户，如果查找出来的用户为null，我们直接返回null，那么subject对象就会收到UnknownAccountException异常
        User user = userService.findByEmail(email);
        if (user==null){
            //我们直接返回null，那么subject对象就会收到UnknownAccountException异常
            return null;
        }
        //3. 对比密码,对比密码的这个过程shiro要自己去完成，你只需要把数据库的密码交给shiro即可。
        /*
          参数一：principal  登录成功后返回的对象
          参数二：credentials  当前用户的数据库密码(这里注意不是用户输入密码)
          参数三：realmName   不需要管理
         */
        AuthenticationInfo authenticationInfo =  new SimpleAuthenticationInfo(user,user.getPassword(),"");
        return authenticationInfo;
    }

    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("=======设置shrio缓存，已经授权！=======");

        // 1.获取到登录成功的用户
        User loginUser = (User) principals.getPrimaryPrincipal();
        // 2.查询登录的用户的权限
        List<Module> userModuleList = moduleService.findModuleByUser(loginUser);
        // 3.把用户具备权限添加到AuthorizationInfo对象中，那么该用户就拥有了这些权限
        //遍历所有的模块，然后把权限添加AuthorizationInfo
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        for (Module module:userModuleList
             ) {
            //添加权限的标记。 注意： 这里的标识只要求唯一性， 我们添加的权限标记可以是模块id也可以是name
            authorizationInfo.addStringPermission(module.getName()); // 日志管理
        }
        return authorizationInfo;
    }
}
